﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;

namespace iStudio.Engine
{
    public class BlockFileHeader : IEquatable<BlockFileHeader>
    {
        const int Size = 4 + 8 + +4 + 4 + 2;

        public int Reserved { get; set; }
        public ulong DataOffset { get; set; }
        public BlockFileEncoding Encoding { get; set; }
        public int SampleRate { get; set; }
        public short Channels { get; set; }

        public int BlockAlign
        {
            get
            {
                int bps;
                switch (Encoding)
                {
                    case BlockFileEncoding.Pcm16:
                        bps = 16; break;
                    case BlockFileEncoding.IeeeFloat32:
                        bps = 32; break;
                    default:
                        throw new InvalidOperationException("Invalid Encoding");
                }
                return bps * Channels;
            }
        }

        public BlockFileHeader()
            : this(44100, 1)
        {

        }

        public BlockFileHeader(int sampleRate, short channels)
        {
            DataOffset = Size;
            Encoding = BlockFileEncoding.IeeeFloat32;

            SampleRate = sampleRate;
            Channels = channels;
        }

        public void WriteToStream(Stream stream)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");
            if (!stream.CanWrite)
                throw new ArgumentException("stream not writeable", "stream");

            BinaryWriter w = new BinaryWriter(stream);
            w.Write(Reserved);
            w.Write(DataOffset);
            w.Write((int)Encoding);
            w.Write(SampleRate);
            w.Write(Channels);
        }

        public void ReadFromStream(Stream stream)
        {
            if (stream == null)
                throw new ArgumentNullException("stream");
            if (!stream.CanRead)
                throw new ArgumentException("stream not readable", "stream");
            if (stream.Length - stream.Position < Size)
                throw new ArgumentException("invalid stream length or position", "stream");

            BinaryReader r = new BinaryReader(stream);
            Reserved = r.ReadInt32();
            DataOffset = r.ReadUInt64();
            Encoding = (BlockFileEncoding)r.ReadInt32();
            SampleRate = r.ReadInt32();
            Channels = r.ReadInt16();
        }

        public bool Equals(BlockFileHeader other)
        {
            bool flag = true;
            flag &= (this.Reserved == other.Reserved);
            flag &= (this.DataOffset == other.DataOffset);
            flag &= (this.Encoding == other.Encoding);
            flag &= (this.SampleRate == other.SampleRate);
            flag &= (this.Channels == other.Channels);
            return flag;
        }
    }
}
